#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2021/4/26 11:26
# @Author  : Grayson Liu
# @Email   : graysonliu@foxmail.com
# @File    : ViewPlanetNDVIForm.py
import threading

import numpy as np
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QFileDialog

from CustomFigureCanvas import CustomFigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from ui.Ui_ViewPlanetNDVIForm import Ui_ViewPlanetNDVIForm
from GeoGraphicProcess import GeoGraphicProcess
from CustomSignal import CustomSignal


class ViewPlanetNDVIForm(QWidget, Ui_ViewPlanetNDVIForm):
    """
    查看NDVI时序图窗体
    """
    global_signal = CustomSignal()

    def __init__(self, parent=None):
        """
        初始化
        :param parent: 父窗体
        """
        super(ViewPlanetNDVIForm, self).__init__(parent)
        self.setupUi(self)

        # 成员变量
        self.path = ""  # Planet遥感影像数据的路径
        self.current_raster = 0  # 当前遥感影像的波段
        self.geo_graphic = GeoGraphicProcess()

        # 添加CustomFigureCanvas到窗体中
        layout = QVBoxLayout(self.figureWidget)
        self.customFig = CustomFigureCanvas(self.figureWidget)
        self.figToolbar = NavigationToolbar(self.customFig, self)
        layout.addWidget(self.customFig)
        layout.addWidget(self.figToolbar)

        # 设置窗体控件的初始状态
        self.lblPath.setText("未选择")
        self.lblPeriod.setText("")
        self.btnPreviousPeriod.setEnabled(False)
        self.btnNextPeriod.setEnabled(False)
        self.btnDrawNDVIFigure.setEnabled(False)

        # 按钮关联槽函数
        self.btnOpenGraphic.clicked.connect(self.open_graphic)
        self.btnPreviousPeriod.clicked.connect(self.get_previous_period)
        self.btnNextPeriod.clicked.connect(self.get_next_period)
        self.btnDrawNDVIFigure.clicked.connect(self.get_ndvi_figure)

        # 自定义信号关联槽函数
        ViewPlanetNDVIForm.global_signal.complete_read_graphic.connect(self.complete_read_graphic)
        ViewPlanetNDVIForm.global_signal.draw_picture.connect(self.show_picture)
        ViewPlanetNDVIForm.global_signal.complete_process.connect(self.complete_process)
        ViewPlanetNDVIForm.global_signal.draw_ndvi_figure.connect(self.draw_ndvi_figure)

    def open_graphic(self):
        """
        按钮“打开遥感影像”的槽函数
        :return:
        """

        def thread_read_graphic(geo_graphic: GeoGraphicProcess, path: str):
            """
            线程体，用于读取遥感影像数据
            :param geo_graphic:
            :param path:
            :return:
            """
            # 读取遥感影像数据信息
            geo_graphic.read_file(path)
            # 获取第1个波段的数据
            im_raster = geo_graphic.get_graphic(1)
            ViewPlanetNDVIForm.global_signal.draw_picture.emit(self.customFig, im_raster)
            # 读取结束之后给Ui线程发信号
            ViewPlanetNDVIForm.global_signal.complete_read_graphic.emit()

        # 打开文件浏览器
        pic_path, pic_type = QFileDialog.getOpenFileName(self, "选择图片文件", filter="GeoTiff Files(*.tif)")
        if pic_path == "":
            return
        # 开启一个线程，用于读取遥感影像数据
        self.lblPath.setText("正在读取...")
        self.path = pic_path
        self.current_raster = 1
        thread = threading.Thread(target=thread_read_graphic, args=(self.geo_graphic, pic_path))
        thread.start()

    def complete_read_graphic(self):
        """
        自定义信号complete_read_graphic的槽函数
        :return:
        """
        self.lblPath.setText(self.path.split("/")[-1])  # 显示文件名
        self.btnPreviousPeriod.setEnabled(True)
        self.btnNextPeriod.setEnabled(True)
        self.btnDrawNDVIFigure.setEnabled(True)
        self.lblPeriod.setText("{} / {}".format(self.current_raster, self.geo_graphic.raster_count))

    def complete_process(self):
        """
        自定义信号complete_process的槽函数，进行处理时，屏蔽相关按钮，处理结束后，解锁相关按钮
        :return:
        """
        self.btnOpenGraphic.setEnabled(True)
        self.btnPreviousPeriod.setEnabled(True)
        self.btnNextPeriod.setEnabled(True)
        self.btnDrawNDVIFigure.setEnabled(True)
        self.lblPeriod.setText("{} / {}".format(self.current_raster, self.geo_graphic.raster_count))

    def get_previous_period(self):
        """
        按钮“上一时期”的槽函数
        :return:
        """

        def thread_show_graphic(geo_graphic: GeoGraphicProcess, raster: int):
            """
            线程体，显示某一个波段的NDVI图像
            :param geo_graphic:
            :param raster:
            :return:
            """
            # 获取某一个波段的数据
            im_raster = geo_graphic.get_graphic(raster)
            ViewPlanetNDVIForm.global_signal.draw_picture.emit(self.customFig, im_raster)
            ViewPlanetNDVIForm.global_signal.complete_process.emit()

        if self.current_raster == 1:
            self.current_raster = self.geo_graphic.raster_count  # 如果是第1个时期，就回到最后一个时期
        else:
            self.current_raster = self.current_raster - 1

        # 屏蔽相关按钮
        self.btnOpenGraphic.setEnabled(False)
        self.btnPreviousPeriod.setEnabled(False)
        self.btnNextPeriod.setEnabled(False)
        self.btnDrawNDVIFigure.setEnabled(False)
        # 启动一个线程进行处理
        thread = threading.Thread(target=thread_show_graphic, args=(self.geo_graphic, self.current_raster))
        thread.start()

    def get_next_period(self):
        """
        按钮“下一时期”的槽函数
        :return:
        """

        def thread_show_graphic(geo_graphic: GeoGraphicProcess, raster: int):
            """
            线程体，显示某一个波段的NDVI图像
            :param geo_graphic:
            :param raster:
            :return:
            """
            # 获取某一个波段的数据
            im_raster = geo_graphic.get_graphic(raster)
            ViewPlanetNDVIForm.global_signal.draw_picture.emit(self.customFig, im_raster)
            ViewPlanetNDVIForm.global_signal.complete_process.emit()

        if self.current_raster == self.geo_graphic.raster_count:
            self.current_raster = 1  # 如果是最后1个时期，就回到第1个时期
        else:
            self.current_raster = self.current_raster + 1

        # 屏蔽相关按钮
        self.btnOpenGraphic.setEnabled(False)
        self.btnPreviousPeriod.setEnabled(False)
        self.btnNextPeriod.setEnabled(False)
        self.btnDrawNDVIFigure.setEnabled(False)
        # 启动一个线程进行处理
        thread = threading.Thread(target=thread_show_graphic, args=(self.geo_graphic, self.current_raster))
        thread.start()

    def get_ndvi_figure(self):
        """
        按钮“绘制”的槽函数，用于画出不同时期NDVI最大值和最小值的折线图
        :return:
        """

        def thread_get_ndvi_figure(geo_graphic: GeoGraphicProcess):
            max_ndvi = []
            min_ndvi = []
            for i in range(self.geo_graphic.raster_count):
                im_raster: np.ndarray = geo_graphic.get_graphic(i + 1)
                max_ndvi.append(np.nanmax(im_raster))
                min_ndvi.append(np.nanmin(im_raster))
            ViewPlanetNDVIForm.global_signal.draw_ndvi_figure.emit(max_ndvi, min_ndvi)
            ViewPlanetNDVIForm.global_signal.complete_process.emit()

        # 屏蔽相关按钮
        self.btnOpenGraphic.setEnabled(False)
        self.btnPreviousPeriod.setEnabled(False)
        self.btnNextPeriod.setEnabled(False)
        self.btnDrawNDVIFigure.setEnabled(False)
        # 启动一个线程进行处理
        thread = threading.Thread(target=thread_get_ndvi_figure, args=(self.geo_graphic, ))
        thread.start()

    def show_picture(self, canvas: CustomFigureCanvas, array: np.ndarray):
        """
        自定义信号draw_picture的槽函数，属于Ui线程，根据传入图片矩阵信息更新控件
        :param canvas: 控件对象
        :param array: 图片矩阵
        :return:
        """
        canvas.show_picture(array)

    def draw_ndvi_figure(self, max_ndvi: list, min_ndvi: list):
        """
        自定义信号draw_ndvi_figure的槽函数，属于Ui线程，根据传入的最大值最小值数据绘制折线图显示在界面上
        :param max_ndvi:
        :param min_ndvi:
        :return:
        """
        self.customFig.show_ndvi_chart(max_ndvi, min_ndvi)
